package com.saver.modules.sys.service;

import com.saver.common.utils.DateUtils;
import com.saver.common.utils.R;
import com.saver.config.ServerConfig;
import com.saver.modules.sys.dao.SysAppendixDao;
import com.saver.modules.sys.entity.SysAppendixEntity;
import com.saver.office.register.OfficeRegister;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;


/**
 * 附件
 *
 * @author yuxiaolong
 * @email 1005471232@qq.com
 * @date 2018年08月30日 下午10:45
 */
@Service
public class SysAppendixService {

    private static Logger logger = LogManager.getLogger(SysAppendixService.class);

    @Autowired
    private ServerConfig serverConfig;

    @Autowired
    private SysAppendixDao sysAppendixDao;

    public R open(Integer id, String uuid, @RequestParam("readOnly") Boolean readOnly) {

        if (id != null) {
            Optional<SysAppendixEntity> byId = sysAppendixDao.findById(id);
            if (byId.isPresent()) {
                SysAppendixEntity sysAppendixEntity = byId.get();
                return openAppendix(sysAppendixEntity, readOnly);
            } else {
                return R.error("文件丢失");
            }
        } else {
            List<SysAppendixEntity> list = sysAppendixDao.findByFileUuid(uuid);
            if (list.size() == 1) {
                SysAppendixEntity sysAppendixEntity = list.get(0);
                return openAppendix(sysAppendixEntity, readOnly);
            } else {
                return R.error("文件丢失");
            }
        }
    }

    private R openAppendix(SysAppendixEntity sysAppendixEntity, Boolean readOnly) {
        try {
            OfficeRegister officeRegister = new OfficeRegister();
            officeRegister.setFileRoot(serverConfig.getUploadPath());
//            在打开word,excel,ppt需要首页的office插件支持。
//            支持在线编辑支持word，excel，ppt。
//            收费使用：qq: 1005471232 ,微信：17521764260，手机号17521764260。价格 5000购买key 永久不限服务器数量。
//            需要电脑安装Microsoft Office 2013以上版本
            officeRegister.setKey("key");
            officeRegister.setRequestUrl(serverConfig.getScheme() + "://" + serverConfig.getIp() + ":" + serverConfig.getPort() + "/office/");
            String absolutePath = getFile(sysAppendixEntity).getAbsolutePath();
            String replace = absolutePath.replace(serverConfig.getUploadPath(), "").replace("\\", "/");

            String register = officeRegister.register("/" + replace, readOnly);
            return R.ok().put("data", register);
        } catch (Exception e) {
            return R.error();
        }
    }

    /**
     * 上传文件
     *
     * @param file
     * @return
     * @throws IOException
     */
    public R uploadFile(MultipartFile file) throws IOException {
        String originalFilename = file.getOriginalFilename();
        String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
        Map uploadFilePath = createUploadFilePath(suffix);

        File outFile = new File((String) uploadFilePath.get("path"));
        File parentFile = outFile.getParentFile();
        if (!parentFile.exists()) {
            parentFile.mkdirs();
        }
        outFile.createNewFile();
        FileOutputStream fileOutputStream = new FileOutputStream(outFile);
        InputStream inputStream = file.getInputStream();
        IOUtils.copy(inputStream, fileOutputStream);
        inputStream.close();
        fileOutputStream.close();
        //添加记录
        SysAppendixEntity entity = new SysAppendixEntity();
        entity.setName(originalFilename);
        entity.setAppendixName((String) uploadFilePath.get("uuid"));
        entity.setCreateDate((Date) uploadFilePath.get("createDate"));
        entity.setSuffix(suffix);
        sysAppendixDao.save(entity);
        logger.info("上传文件：" + originalFilename);
        return R.ok().put("fileName", originalFilename).put("appendixId", entity.getId());
    }


    /**
     * 关联文件和所属数据
     *
     * @param id
     * @param uuid
     */
    public void update(Integer id, String uuid) {
        Optional<SysAppendixEntity> byId = sysAppendixDao.findById(id);
        if (byId.isPresent()) {
            SysAppendixEntity sysAppendixEntity = byId.get();
            sysAppendixEntity.setFileUuid(uuid);
            sysAppendixDao.save(sysAppendixEntity);
        }
    }

    private void download(SysAppendixEntity item, HttpServletResponse response, ServletOutputStream outputStream) throws IOException {
        File file = getFile(item);
        Path path = Paths.get(file.getAbsolutePath());
        response.setContentType(Files.probeContentType(path));
        response.setContentType("multipart/form-data");
        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
        response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(item.getName(), "utf-8").replace("+", "%20"));
        if (file.exists()) {
            FileInputStream stream = new FileInputStream(file);
            IOUtils.copy(stream, outputStream);
            stream.close();
        }
        outputStream.close();
    }

    /**
     * 下载全部文件
     *
     * @param uuid
     * @param response
     * @throws IOException
     */
    public void download(String uuid, HttpServletResponse response) throws IOException {
        ServletOutputStream outputStream = response.getOutputStream();
        List<SysAppendixEntity> list = sysAppendixDao.findByFileUuid(uuid);
        if (list.size() == 1) {
            download(list.get(0), response, outputStream);
        } else if (list.size() > 1) {
            response.setContentType("multipart/form-data");
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode("打包文件.zip", "utf-8"));
            ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);
            for (SysAppendixEntity sysAppendixEntity : list) {
                File file = getFile(sysAppendixEntity);
                FileInputStream fileInputStream = new FileInputStream(file);
                ZipEntry zipEntry = new ZipEntry(sysAppendixEntity.getSuffix().substring(1) + "/" + sysAppendixEntity.getAppendixName() + sysAppendixEntity.getSuffix());
                zipOutputStream.putNextEntry(zipEntry);
                IOUtils.copy(fileInputStream, zipOutputStream);
            }
            zipOutputStream.close();
        }

    }

    /**
     * 下载文件
     *
     * @param id
     * @param response
     * @throws IOException
     */
    public void downloadAppendix(Integer id, HttpServletResponse response) throws IOException {
        Optional<SysAppendixEntity> byId = sysAppendixDao.findById(id);
        if (!byId.isPresent()) {
            return;
        }
        ServletOutputStream outputStream = response.getOutputStream();
        response.setContentType("multipart/form-data");
        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
        download(byId.get(), response, outputStream);
    }


    /**
     * 删除全部文件
     *
     * @param uuid
     * @return
     */
    @Transactional
    public R delete(String uuid) {
        List<SysAppendixEntity> byFileUuid = sysAppendixDao.findByFileUuid(uuid);
        for (SysAppendixEntity sysAppendixEntity : byFileUuid) {
            this.deleteAppendix(sysAppendixEntity.getId());
        }
        return R.ok();
    }


    /**
     * 删除文件
     *
     * @param id
     * @return
     */
    @Transactional
    public R deleteAppendix(Integer id) {
        Optional<SysAppendixEntity> byId = sysAppendixDao.findById(id);
        SysAppendixEntity entity = byId.get();
        File file = getFile(entity);
        if (file.exists()) {
            file.delete();
        }
        sysAppendixDao.deleteById(id);
        return R.ok();
    }

    public File getFile(SysAppendixEntity entity) {
        String rootPath = serverConfig.getUploadPath();
        File file = new File(rootPath);
        if (!file.exists()) {
            file.mkdirs();
        }
        String format = DateUtils.format(entity.getCreateDate(), "yyyy-MM-dd");
        return new File(serverConfig.getUploadPath() + "/" + entity.getSuffix().substring(1) + "/" + format + "/" + entity.getAppendixName() + entity.getSuffix());
    }

    public Map createUploadFilePath(String suffix) {
        String rootPath = serverConfig.getUploadPath();
        File file = new File(rootPath);
        if (!file.exists()) {
            file.mkdirs();
        }
        //保存文件
        Date createDate = new Date();
        String format = DateUtils.format(createDate, "yyyy-MM-dd");
        String uuid = UUID.randomUUID().toString().replace("-", "");
        String path = serverConfig.getUploadPath() + "/" + suffix.substring(1) + "/" + format + "/" + uuid + suffix;
        Map<String, Object> map = new HashedMap();
        map.put("createDate", createDate);
        map.put("uuid", uuid);
        map.put("path", path);
        return map;
    }

}
